package middleware

import (
	"bytes"
	"encoding/json"
	"fmt"
	"io"
	"strings"
	"time"
	"wms/internal/model"
	"wms/pkg/database"
	"wms/pkg/logger"
	"wms/pkg/utils"

	"github.com/gin-gonic/gin"
	"go.uber.org/zap"
)

type responseBodyWriter struct {
	gin.ResponseWriter
	body *bytes.Buffer
}

func (r responseBodyWriter) Write(b []byte) (int, error) {
	r.body.Write(b)
	return r.ResponseWriter.Write(b)
}

// OperationLog 操作日志中间件
func OperationLog() gin.HandlerFunc {
	return func(c *gin.Context) {
		// 不记录OPTIONS请求
		if c.Request.Method == "OPTIONS" {
			c.Next()
			return
		}

		// 不记录静态资源请求
		if strings.HasPrefix(c.Request.URL.Path, "/static") {
			c.Next()
			return
		}

		// 不记录Swagger请求
		if strings.HasPrefix(c.Request.URL.Path, "/swagger") {
			c.Next()
			return
		}

		// 如果系统没有安装，或者是安装接口，不记录日志
		if strings.HasPrefix(c.Request.URL.Path, "/api/v1/test/database") {
			c.Next()
			return
		}

		// 记录请求开始时间
		startTime := time.Now()

		// 记录请求体
		var requestBody []byte
		if c.Request.Body != nil {
			// 检查是否跳过请求体日志记录
			skipRequestBodyLog, _ := c.Get("skip_request_body_log")

			// 检查Content-Type是否包含multipart/form-data，通常表示文件上传
			contentType := c.GetHeader("Content-Type")
			isFileUpload := strings.Contains(contentType, "multipart/form-data")

			if skipRequestBodyLog == true || isFileUpload {
				// 对于文件上传请求，不记录请求体，避免二进制数据导致数据库错误
				requestBody = []byte("[文件上传请求，请求体已省略]")
			} else {
				// 正常记录请求体
				requestBody, _ = io.ReadAll(c.Request.Body)
				c.Request.Body = io.NopCloser(bytes.NewBuffer(requestBody))
			}
		}

		// 包装 ResponseWriter
		w := &responseBodyWriter{body: &bytes.Buffer{}, ResponseWriter: c.Writer}
		c.Writer = w

		// 处理请求
		c.Next()

		// 获取当前用户
		userID, _ := c.Get("user_id")
		username, _ := c.Get("username")

		// 获取模块和操作
		path := c.Request.URL.Path
		method := c.Request.Method

		// 安全地获取模块名
		module := "system" // 默认模块名
		pathParts := strings.Split(strings.Trim(path, "/"), "/")
		if len(pathParts) > 1 {
			module = pathParts[1]
		}
		action := getAction(method, path)

		// 异步记录日志
		go func() {
			if db := database.GetDB(); db != nil {
				log := &model.OperationLog{
					UserID:      utils.ToUint(userID),
					Username:    utils.ToString(username),
					Module:      module,
					Action:      action,
					Method:      method,
					Path:        path,
					IP:          c.ClientIP(),
					RequestData: string(requestBody),
					Response:    w.body.String(),
					Status:      c.Writer.Status(),
					Duration:    time.Since(startTime).Milliseconds(),
				}

				if err := db.Create(log).Error; err != nil {
					logger.Error("保存操作日志失败",
						zap.Error(err),
						zap.String("path", path),
						zap.String("method", method),
					)
				}
			}
		}()

		go func() {
			if db := database.GetDB(); db != nil {
				// 从请求数据中提取操作对象的关键信息
				targetName := extractTargetName(string(requestBody), method, path)

				log := &model.OperationLog{
					UserID:      utils.ToUint(userID),
					Username:    utils.ToString(username),
					Module:      module,
					Action:      action,
					Method:      method,
					Path:        path,
					IP:          c.ClientIP(),
					RequestData: string(requestBody),
					Response:    w.body.String(),
					Status:      c.Writer.Status(),
					Duration:    time.Since(startTime).Milliseconds(),
					TargetName:  targetName,
				}

				if err := db.Create(log).Error; err != nil {
					logger.Error("保存操作日志失败",
						zap.Error(err),
						zap.String("path", path),
						zap.String("method", method),
					)
				}
			}
		}()
	}
}

// getAction 获取更详细的操作描述
func getAction(method string, path string) string {
	// 提取具体的业务模块和操作
	parts := strings.Split(strings.Trim(path, "/"), "/")
	if len(parts) < 3 {
		return defaultAction(method)
	}

	module := parts[1]
	operation := parts[2]

	// 用户相关操作
	if module == "user" || module == "users" {
		if operation == "login" {
			return "用户登录"
		} else if operation == "logout" {
			return "用户退出"
		} else if operation == "profile" {
			return "查看个人信息"
		} else if method == "PUT" && (operation == "profile" || operation == "password") {
			return "修改个人信息"
		} else if method == "GET" && len(parts) > 3 {
			return "查看用户详情"
		} else if method == "POST" {
			return "创建用户"
		} else if method == "PUT" {
			return "更新用户"
		} else if method == "DELETE" {
			return "删除用户"
		}
	}

	// 仓库和库存相关操作
	if module == "warehouse" || module == "inventory" {
		if method == "GET" && operation == "list" {
			return "查询库存列表"
		} else if method == "GET" && operation == "stats" {
			return "查看库存统计"
		} else if operation == "count" || operation == "check" {
			return "盘点库存"
		} else if operation == "alerts" {
			return "查看库存预警"
		} else if operation == "adjust" {
			return "调整库存"
		} else if operation == "move" {
			return "移动库存"
		} else if operation == "category" {
			if method == "POST" {
				return "创建库存分类"
			} else if method == "PUT" {
				return "更新库存分类"
			} else if method == "DELETE" {
				return "删除库存分类"
			}
		}
	}

	// 入库相关操作
	if module == "inbound" {
		if method == "GET" && operation == "list" {
			return "查询入库单"
		} else if method == "GET" && len(parts) > 3 {
			return "查看入库单详情"
		} else if method == "POST" {
			return "创建入库单"
		} else if method == "PUT" && (operation == "confirm" || operation == "complete") {
			return "确认入库"
		} else if method == "PUT" && operation == "cancel" {
			return "取消入库单"
		}
	}

	// 出库相关操作
	if module == "outbound" {
		if method == "GET" && operation == "list" {
			return "查询出库单"
		} else if method == "GET" && len(parts) > 3 {
			return "查看出库单详情"
		} else if method == "POST" {
			return "创建出库单"
		} else if method == "PUT" && (operation == "confirm" || operation == "complete") {
			return "确认出库"
		} else if method == "PUT" && operation == "cancel" {
			return "取消出库单"
		}
	}

	// 供应商相关操作
	if module == "supplier" || module == "suppliers" {
		if method == "GET" && operation == "list" {
			return "查询供应商列表"
		} else if method == "GET" && len(parts) > 3 {
			return "查看供应商详情"
		} else if method == "POST" {
			return "添加供应商"
		} else if method == "PUT" {
			return "更新供应商信息"
		} else if method == "DELETE" {
			return "删除供应商"
		}
	}

	// 系统设置相关操作
	if module == "system" || module == "settings" {
		if operation == "logs" {
			return "查看系统日志"
		} else if operation == "config" {
			if method == "GET" {
				return "查看系统配置"
			} else if method == "PUT" {
				return "更新系统配置"
			}
		} else if operation == "backup" {
			return "系统备份"
		} else if operation == "restore" {
			return "系统恢复"
		}
	}

	// 如果没有匹配到具体操作，则返回默认操作类型
	return defaultAction(method)
}

// defaultAction 根据HTTP方法返回默认操作类型
func defaultAction(method string) string {
	switch method {
	case "GET":
		return "查询"
	case "POST":
		return "创建"
	case "PUT":
		return "更新"
	case "DELETE":
		return "删除"
	default:
		return "未知"
	}
}

// 添加新函数 extractTargetName 从请求中提取目标对象名称
func extractTargetName(requestBody string, method string, path string) string {
	// 对于GET请求，通常从路径中提取ID
	if method == "GET" {
		parts := strings.Split(strings.Trim(path, "/"), "/")
		if len(parts) > 3 {
			return parts[3] // 可能是ID
		}
		return ""
	}

	// 对于POST/PUT请求，尝试从请求体中提取名称字段
	if (method == "POST" || method == "PUT") && requestBody != "" {
		var data map[string]interface{}
		if err := json.Unmarshal([]byte(requestBody), &data); err == nil {
			// 常见的名称字段
			nameFields := []string{"name", "title", "label", "username", "code", "productName", "supplierName"}
			for _, field := range nameFields {
				if value, ok := data[field]; ok && value != nil {
					if strValue, ok := value.(string); ok && strValue != "" {
						return strValue
					}
				}
			}

			// 如果有ID字段，也可以返回
			if id, ok := data["id"]; ok && id != nil {
				return fmt.Sprintf("ID:%v", id)
			}
		}
	}

	return ""
}
